package com.lin.filegraph.utils.filedg;

import com.lin.filegraph.utils.calculator.CodeSizeCalculator;
import com.lin.filegraph.utils.model.MethodInfo;
import com.lin.filegraph.utils.parser.astvisitor.CognCompVisitor;
import com.lin.filegraph.utils.parser.node.JFileNode;
import com.lin.filegraph.utils.parser.node.JMethodNode;
import com.lin.filegraph.utils.parser.simpleast.SimpleASTHelper;

import java.util.ArrayList;
import java.util.List;

/**
 * @description:
 * @author: linhuaixu
 * @time: 2023/5/18 11:01
 */

public class FileInfo {
    private JFileNode fileNode;// 文件节点
    private String strComponentName = null;// 组件名
    private FileGraph subFDG;
    private int LOC = 0;// 代码行
    private int validLOC;// 有效代码行
    private int cyclomaticComplexity = 0;// 圈复杂度
    private int outDegreeInFDG = 0;// 出度
    private int inDegreeInFDG = 0;// 入度
    private int outDegreeInCompFDG = 0;// 组件中文件依赖子图的出度
    private int inDegreeInCompFDG = 0;// 组件中文件依赖子图的入度
    private int cognComplexity = 0;
    private List<String> elements;

    private int apiNum = 0;
    private int commentedApiNum = 0;
    private int paramNumOfAllApi = 0;
    private int methodNum = 0;
    private int commentedMethodNum = 0;

    private List<MethodInfo> listOfMethodInfo = new ArrayList<>();

    public FileInfo(JFileNode fileNode, String strComponentName, FileGraph subFDG) {
        super();
        this.fileNode = fileNode;
        this.strComponentName = strComponentName;
        this.subFDG = subFDG;
        listOfMethodInfo = new ArrayList<>();
    }

    public int getApiNum() {
        return apiNum;
    }

    public int getCommentedApiNum() {
        return commentedApiNum;
    }

    public int getParamNumOfAllApi() {
        return paramNumOfAllApi;
    }

    public int getMethodNum() {
        return methodNum;
    }

    public int getCommentedMethodNum() {
        return commentedMethodNum;
    }

    public JFileNode getFileNode() {
        return fileNode;
    }

    public void calculateFileInfo() {
        FileGraph fdg = fileNode.getRoot().getFdg();
        for (JMethodNode method : SimpleASTHelper.findAllMethodsInSubTree(fileNode)) {
            MethodInfo methodInfo = new MethodInfo(method, strComponentName);

            methodInfo.calculateMethodInfo();
            listOfMethodInfo.add(methodInfo);
        }
        for(MethodInfo mInfo : listOfMethodInfo) {
            cyclomaticComplexity += mInfo.getCyclomaticComplexity();
            this.methodNum ++;
            if(mInfo.isAPI()) {
                this.apiNum ++;
                this.paramNumOfAllApi += mInfo.getMethodNode().getAllParameters().size();
            }
            if(mInfo.isHasComment()) {
                this.commentedMethodNum ++;
                if(mInfo.isAPI()) {
                    this.commentedApiNum ++;
                }
            }
        }
        CognCompVisitor cognCompVisitor = new CognCompVisitor(fileNode);
        cognCompVisitor.traverse();
        cognComplexity = cognCompVisitor.getCognComp();
        elements = new ArrayList<>();
//		System.out.println("cognComplexity: " + fileNode.getFilePath() + " "+ cognComplexity);
        LOC = CodeSizeCalculator.calculateSizeOfNode(fileNode);
        validLOC = CodeSizeCalculator.calculateValidSizeOfNode(fileNode);
        // ��ȡ����ȡ����ò��
        inDegreeInFDG = fdg.getPreFiles(fdg.getFileGraphNode(fileNode.getFilePath())).size();
        outDegreeInFDG = fdg.getPostFiles(fdg.getFileGraphNode(fileNode.getFilePath())).size();
        inDegreeInCompFDG = subFDG.getPreFiles(fdg.getFileGraphNode(fileNode.getFilePath())).size();
        outDegreeInCompFDG = subFDG.getPostFiles(fdg.getFileGraphNode(fileNode.getFilePath())).size();
    }

    public void displayFileBasicInfo() {
        System.out.println("display file basic info ...");
        System.out.println(fileNode);
        System.out.println("strComponentName:" + strComponentName);
        System.out.println("outDegreeInFDG:" + outDegreeInFDG);
        System.out.println("inDegreeInFDG:" + inDegreeInFDG);
        System.out.println("outDegreeInCompFDG:" + outDegreeInCompFDG);
        System.out.println("inDegreeInCompFDG:" + inDegreeInCompFDG);
    }

    public MethodInfo getMethodInfo(JMethodNode methodNode) {// �÷���ǩ��
        for (MethodInfo mInfo : listOfMethodInfo) {
            if (mInfo.getMethodNode().equals(methodNode)) {
                return mInfo;
            }
        }
        return null;
    }

    public int getLOC() {
        return LOC;
    }

    public int getCyclomaticComplexity() {
        return cyclomaticComplexity;
    }

    public int getOutDegreeInFDG() {
        return outDegreeInFDG;
    }

    public int getInDegreeInFDG() {
        return inDegreeInFDG;
    }

    public String getStrComponentName() {
        return strComponentName;
    }

    public int getOutDegreeInCompFDG() {
        return outDegreeInCompFDG;
    }

    public int getInDegreeInCompFDG() {
        return inDegreeInCompFDG;
    }

    public List<MethodInfo> getListOfMethodInfo() {
        return listOfMethodInfo;
    }

    /**
     * @return
     */
    public int getValidLOC() {
        return validLOC;
    }

    public int getCognComplexity() {
        return cognComplexity;
    }

    public List<String> getElements() {
        return elements;
    }
    public String getStrElements() {
        StringBuilder sb = new StringBuilder();
        if(elements.isEmpty()) {
            return "";
        }
        for(String element : elements) {
            sb.append(element + ",");
        }
        return sb.toString().substring(0, sb.length() - 1);
    }

}

